﻿using Pipes.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Pipes.UnitTest
{
    
    
    /// <summary>
    ///This is a test class for DelimitedStreamReaderTest and is intended
    ///to contain all DelimitedStreamReaderTest Unit Tests
    ///</summary>
  [TestClass()]
  public class DelimitedTextReaderTest
  {


    private TestContext testContextInstance;

    /// <summary>
    ///Gets or sets the test context which provides
    ///information about and functionality for the current test run.
    ///</summary>
    public TestContext TestContext
    {
      get
      {
        return testContextInstance;
      }
      set
      {
        testContextInstance = value;
      }
    }

    #region Additional test attributes
    // 
    //You can use the following additional attributes as you write your tests:
    //
    //Use ClassInitialize to run code before running the first test in the class
    //[ClassInitialize()]
    //public static void MyClassInitialize(TestContext testContext)
    //{
    //}
    //
    //Use ClassCleanup to run code after all tests in a class have run
    //[ClassCleanup()]
    //public static void MyClassCleanup()
    //{
    //}
    //
    //Use TestInitialize to run code before running each test
    //[TestInitialize()]
    //public void MyTestInitialize()
    //{
    //}
    //
    //Use TestCleanup to run code after each test has run
    //[TestCleanup()]
    //public void MyTestCleanup()
    //{
    //}
    //
    #endregion


    [TestMethod()]
    public void SimpleDelimiterTest()
    {
      var input = "|123|4|56||78912|456|123|4|56||78912|456|||123|4|56||78912|456||||";
      var expected = input.Split('|');
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.AddDelim('|');
      for (int i = 5; i < 70; i += 5)
      {
        reader.BufferSize = i;
        var actual = reader.ToArray();
        CollectionAssert.AreEqual(expected, actual);
      }
    }
    [TestMethod()]
    public void SimpleDelimiterTestSkipEmpty()
    {
      var input = "123|4|56||78912|456";
      var expected = input.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.SkipEmpty = true;
      reader.AddDelim('|');
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void ComplexDelimiterTest()
    {
      var input = "\"abc\",123,,\"first, \"\" second\",abc\"";
      var expected = new List<string>() { "abc", "123", "", "first, \"\" second", "abc\"" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.FieldEnclosingChar = '"';
      reader.AddDelim(',');
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void ComplexDelimiterTest2()
    {
      var input = "\"abc\",123,,\"first, \"\" second\",abc\"";
      var expected = new List<string>() { "abc", "123", "", "first, \" second", "abc\"" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.FieldEnclosingChar = '"';
      reader.EnclosingCharEscape = '"';
      reader.AddDelim(',');
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void ComplexDelimiterTest3()
    {
      var input = "\"abc\",123,,\"first, \\\" \\second\",abc\"";
      var expected = new List<string>() { "abc", "123", "", "first, \" \\second", "abc\"" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.FieldEnclosingChar = '"';
      reader.EnclosingCharEscape = '\\';
      reader.AddDelim(',');
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void ComplexDelimiterTestSkipEmpty()
    {
      var input = ",,,\"abc\",123,,\"first, \\\" \\second\",abc,,\"\",";
      var expected = new List<string>() { "abc", "123", "first, \" \\second", "abc" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.FieldEnclosingChar = '"';
      reader.EnclosingCharEscape = '\\';
      reader.AddDelim(',');
      reader.SkipEmpty = true;
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void NewLineDelimiter()
    {
      var input = "value1\r\rvalue2\nvalue3\r\n\r\nvalue4\n";
      var expected = new List<string>() { "value1", "", "value2", "value3", "", "value4", "" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.AddDelim(Environment.NewLine);
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void NewLineDelimiterSkipEmpty()
    {
      var input = "value1\r\rvalue2\nvalue3\r\n\r\nvalue4\n";
      var expected = new List<string>() { "value1", "value2", "value3", "value4" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.AddDelim(Environment.NewLine);
      reader.SkipEmpty = true;
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void StringDelimiter()
    {
      var input = "value1 |  | value2 | value3 |  | value4 | ";
      var expected = new List<string>() { "value1", "", "value2", "value3", "", "value4", "" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.AddDelim(" | ");
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void StringDelimiterSkipEmpty()
    {
      var input = "value1 |  | value2 | value3 |  | value4 | ";
      var expected = new List<string>() { "value1", "value2", "value3", "value4" };
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.AddDelim(" | ");
      reader.SkipEmpty = true;
      var actual = reader.ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void CsvParseTest()
    {
      var input = "\"Bob said, \"\"Hey!\"\"\",2, 3 ";
      var expected = new List<string>() { @"Bob said, ""Hey!""", "2", " 3 " };
      var actual = CsvReader(input).ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void CsvParseTest2()
    {
      var input = "1\r2\n";
      var expected = new List<string>() { "1", "2", "" };
      var actual = CsvReader(input).ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }
    [TestMethod()]
    public void CsvParseTest3()
    {
      var input = "\"\n\r\n\n\r\r\",,\t,\n";
      var expected = new List<string>() { "\n\r\n\n\r\r", "", "\t", "", "" };
      var actual = CsvReader(input).ToArray();
      CollectionAssert.AreEqual(expected, actual);
    }

    private DelimitedTextReader CsvReader(string input)
    {
      var reader = new IO.StringTextSource(input).Pipe(new DelimitedTextReader());
      reader.AddDelim(',');
      reader.FieldEnclosingChar = '"';
      reader.EnclosingCharEscape = '"';
      reader.AddDelim(Environment.NewLine);
      return reader;
    }
  }
}
